#include "myglib.h"

GList*
g_list_collect (GList        *list,
                GCollectFunc  func,
                gpointer      user_data)
{
  GList *previous_result = NULL;
  GList *first_result;
  guint key = 0;

  if (! list)
    return NULL;

  /* First item */
  first_result = g_list_alloc();
  first_result->data = (*func) (key++, list->data, user_data);
  first_result->prev = NULL;

  previous_result = first_result;
  list = list->next;

  /* Any remaining items */
  while (list)
    {
      GList *new_result = g_list_alloc();
      new_result->data = (*func) (key++, list->data, user_data);
      new_result->prev = previous_result;
      previous_result->next = new_result;

      previous_result = new_result;
      list = list->next;
    }

  // Last result has no next
  previous_result->next = NULL;

  return first_result;
}


static void
insert_hash_table_entry(gpointer key,
                        gpointer value,
                        GHashTable *hashtable)
{
  g_hash_table_insert(hashtable, key, value);
}


void
g_hash_table_insert_all(GHashTable *hashtable,
                        GHashTable *items)
{
  g_hash_table_foreach(items,
                       (GHFunc)insert_hash_table_entry,
                       (gpointer)hashtable);
}


typedef struct {
  GHashTable *result;
  GHCollectFunc function;
  gpointer user_data;
} CollectData;

static void
collect_item(gpointer key, gpointer value, CollectData *collect_data)
{
  gpointer result = (*collect_data->function)(key,
                                              value,
                                              collect_data->user_data);

  g_hash_table_insert(collect_data->result, key, result);
}

GHashTable *
g_hash_table_collect (GHashTable    *hashtable,
                      GHCollectFunc  func,
                      gpointer       user_data,
                      GHashFunc      hash,
                      GCompareFunc   compare)
{
  CollectData collect_data;
  collect_data.result = g_hash_table_new(hash, compare);
  collect_data.function = func;
  collect_data.user_data = user_data;
  g_hash_table_foreach(hashtable,
                       (GHFunc) collect_item,
                       (gpointer) &collect_data);
  return collect_data.result;
}
